using UnityEngine;

public class Game : MonoBehaviour
{
    public int width = 10;
    public int height = 10;
    [SerializeField]
    private int minesCount = 5;
    private Board board;
    private Cell[,] state;
    private bool gameOver;
    void OnValidate()
    {
        minesCount = Mathf.Clamp(minesCount, 0, width * height);
    }
    private void Awake()
    {
        gameOver = false;
        board = GetComponentInChildren<Board>();
    }

    private void Start()
    {
        NewGame();
    }

    private void NewGame()
    {
        // 绘制棋盘大小
        state = new Cell[width, height];
        // 生成单元格
        GeneratedCells();
        // 生成地雷
        GeneratedMines();
        // 生成雷周围的数字
        GeneratedNumber();
        // 调整摄像机位置
        Camera.main.gameObject.transform.position = new Vector3(width / 2f, height / 2f, -10f);
        board.Draw(state);
    }
    // 生成单元格
    private void GeneratedCells()
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                state[x, y] = new()
                {
                    position = new Vector3Int(x, y, 0),
                    type = Cell.Type.Empty
                };
            }
        }
    }
    // 生成地雷
    private void GeneratedMines()
    {
        for (int i = 0; i < minesCount; i++)
        {
            // 获取随机位置
            int x = Random.Range(0, width);
            int y = Random.Range(0, height);
            // 防止位置重复
            if (state[x, y].type == Cell.Type.Mine) i--;
            // 设置这个位置为地雷
            state[x, y].type = Cell.Type.Mine;
        }
    }
    // 生成数字
    private void GeneratedNumber()
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                if (state[x, y].type == Cell.Type.Mine) continue;

                state[x, y].number = CountMines(x, y);

                if (state[x, y].number > 0) state[x, y].type = Cell.Type.Number;
            }
        }
    }
    // 获取周围地雷数量
    private int CountMines(int cellX, int cellY)
    {
        int count = 0;
        //边界检测位置偏移量
        Vector2Int[] neighborOffsets = new Vector2Int[] {
            new(-1, -1), new(-1, 0), new(-1, 1), new(0, -1),
            new(0, 1), new(1, -1),  new(1, 0),  new(1, 1)
        };

        foreach (Vector2Int offset in neighborOffsets)
        {
            // 取到自身周围的位置
            int neighborX = cellX + offset.x;
            int neighborY = cellY + offset.y;

            // 检查是否超出棋盘边界
            if (neighborX >= 0 && neighborX < width &&
                neighborY >= 0 && neighborY < height)
            {
                // 如果相邻单元格是地雷，计数+1
                if (GetCell(neighborX, neighborY).type == Cell.Type.Mine)
                {
                    count++;
                }
            }
        }
        return count;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            NewGame();
            gameOver = false;
        }
        else if (!gameOver)
        {
            if (Input.GetMouseButtonDown(1))
            {
                Flag();
            }
            else if (Input.GetMouseButtonDown(0))
            {
                Reveal();
            }
        }
    }

    // 插旗功能
    private void Flag()
    {
        Vector3Int cellPosition = GetPosition();
        Cell cell = GetCell(cellPosition.x, cellPosition.y); // 获取当前被点击的单元格
        // 如果位置不存在单元格或者当前单元格已经被揭开 返回
        if (cell.type == Cell.Type.IsValid || cell.revealed) return;
        // 反转旗帜状态
        cell.flagged = !cell.flagged;
        state[cellPosition.x, cellPosition.y] = cell;   // 设置当前单元格状态
        // 更新画板
        board.Draw(state);
    }

    private Vector3Int GetPosition()
    {
        Vector3 worldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); // 获取世界坐标
        Vector3Int cellPosition = board.Tilemap.WorldToCell(worldPosition); // 将世界坐标转换成本地坐标
        return cellPosition;
    }

    // 揭开功能
    private void Reveal()
    {
        Vector3Int cellPosition = GetPosition();
        Cell cell = GetCell(cellPosition.x, cellPosition.y); // 获取当前被点击的单元格
        // 如果位置不存在单元格或者当前单元格已经被揭开 返回
        if (cell.type == Cell.Type.IsValid || cell.revealed || cell.flagged) return;

        switch (cell.type)
        {
            case Cell.Type.Empty:
                Flood(cell);    // 如果当前单元格是空的，递归遍历旁边的单元格
                CheckWinCondition();
                break;
            case Cell.Type.Mine:
                Explode(cell);  // 如果是地雷 结束游戏
                break;
            default:
                cell.revealed = true;// 设置揭开状态
                state[cellPosition.x, cellPosition.y] = cell;   // 设置当前单元格状态
                CheckWinCondition();
                break;
        }
        // 更新画板
        board.Draw(state);
    }

    private void Flood(Cell cell)
    {
        // 如果是点击的单元格 退出
        if (cell.revealed) return;
        // 如果单元格是地雷或超出地图 退出
        if (cell.type == Cell.Type.Mine || cell.type == Cell.Type.IsValid) return;
        // 设置这个单元格为被点击状态
        cell.revealed = true;
        // 将状态设置到单元格中
        state[cell.position.x, cell.position.y] = cell;
        // 如果类型是空的 递归遍历上下左右四个方向的其他单元格
        if (cell.type == Cell.Type.Empty)
        {
            Flood(GetCell(cell.position.x + 1, cell.position.y));
            Flood(GetCell(cell.position.x - 1, cell.position.y));
            Flood(GetCell(cell.position.x, cell.position.y + 1));
            Flood(GetCell(cell.position.x, cell.position.y - 1));
        }
    }
    // 游戏结束Lose
    private void Explode(Cell cell)
    {
        gameOver = true;
        Debug.Log("GAME OVER! SMALL ASS");
        cell.exploded = true;
        cell.revealed = true;
        state[cell.position.x, cell.position.y] = cell;

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                cell = state[x, y];
                if (cell.type == Cell.Type.Mine)
                {
                    cell.revealed = true;
                    state[x, y] = cell;
                }
            }
        }
    }
    // 游戏结束Win
    private void CheckWinCondition()
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                if (state[x, y].type != Cell.Type.Mine && !state[x, y].revealed) return;
            }
        }
        Debug.Log("FUCK YOU WIN!");
        gameOver = true;
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                if (state[x, y].type == Cell.Type.Mine)
                {
                    state[x, y].revealed = true;
                }
            }
        }
    }
    // 获取单元格
    private Cell GetCell(int x, int y)
    {
        return IsValid(x, y) ? state[x, y] : new Cell();
    }
    // 检测单元格是否超出边界
    private bool IsValid(int x, int y)
    {
        return x >= 0 && x < width && y >= 0 && y < height;
    }

}
